#include "networkcommunicator.h"
#include <QDebug>
#include <QRegExp>
#include <QtGui>
#include <QNetworkConfigurationManager>
#include "playlist.h"


NetworkCommunicator::NetworkCommunicator(QObject *parent) : QObject(parent)
{
    QNetworkConfigurationManager conf;
    session = new QNetworkSession(conf.defaultConfiguration(), this);
    session->open();
 }

void NetworkCommunicator::findStreamUrl(VideoInfo vid)
{
    currentvid= vid;
    qDebug() << "Launching request for: www.youtube.com/get_video_info?video_id=" +vid.id;
    QNetworkRequest request(QUrl("http://www.youtube.com/get_video_info?video_id=" + vid.id));
    QNetworkReply* reply = mgr.get(request);

    connect(reply, SIGNAL(finished()), this, SLOT(gotVideoInfo()));
}

void NetworkCommunicator::gotVideoInfo()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
    qDebug("Retrieved video info! Bytes received:");
    qDebug(QString::number(reply->bytesAvailable()).toStdString().c_str());
    if(reply->bytesAvailable() < 2000)
    {
        currentvid.id += "&el=vevo";
        findStreamUrl(currentvid);
        return;
    }

    QString data = QString::fromUtf8(reply->readAll());

    //data = data.left(1000);

    // GET TOKEN
    QRegExp regex = QRegExp("^.*&token=([^&]+).*$");
    bool foundToken = regex.exactMatch(data);
    qDebug(QString("Found token: %1").arg(foundToken).toAscii());
    if(foundToken)
    {
        QString token = regex.cap(1);
        while(token.contains("%"))
            token = QByteArray::fromPercentEncoding(token.toAscii());
        qDebug(token.toAscii());
    }
    else
    {
        qDebug("failed to find token");
    }

    // GET STREAM URL
    QRegExp r("^.*url%3D([^&]+).*$");
    bool foundStreamUrl = r.exactMatch(data);
    if(foundStreamUrl)
    {
        QString streamUrl( r.cap(1));

        streamUrl = QByteArray::fromPercentEncoding(streamUrl.toAscii());

        QStringList urls = streamUrl.split(",", QString::SkipEmptyParts);
        for(QList<QString>::Iterator itr = urls.begin(); itr != urls.end(); itr++)
        {
            QString url = (*itr);
            while(url.contains("%"))
                url = QByteArray::fromPercentEncoding(url.toAscii());
            if(url.contains("itag=34")){
                url = url.left(url.indexOf("&quality="));
                emit newStreamUrlFound(QUrl(url));
            }
        }

    }
    else
    {
        qDebug("failed to find stream");
    }

}

void NetworkCommunicator::search(QString tag)
{
    tag = tag.trimmed();
    tag.replace(' ', '/');
    QNetworkRequest request(QUrl("https://gdata.youtube.com/feeds/api/videos/-/" + tag + "?v=2&format=5"));
    QNetworkReply* reply = mgr.get(request);

    connect(reply, SIGNAL(finished()), this, SLOT(videoSearchCompleted()));
}

void NetworkCommunicator::videoSearchCompleted()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());

    QString data = QString::fromUtf8(reply->readAll());


    QList<VideoInfo> vidlist;

    pugi::xml_document file;
    file.load_buffer(data.toStdString().c_str(), data.toStdString().size());

    for(pugi::xml_node entry = file.child("feed").child("entry"); entry; entry = entry.next_sibling())
    {
        qDebug("analyzing entry");
        VideoInfo vid;
        QString title = entry.child("title").text().as_string();
        if(title.indexOf("-") != -1)
        {
            vid.title = title.right(title.length() - 2 - title.indexOf("-"));
            vid.artist = title.left(title.indexOf("-"));
        }
        else
        {
            vid.title = title;
            vid.artist = "";
        }
        vid.id = entry.child("media:group").child("yt:videoid").text().as_string();
        vid.duration = entry.child("media:group").child("yt:duration").attribute("seconds").as_int();
        vid.viewCount = entry.child("yt:statistics").attribute("viewCount").as_int();
        qDebug() << vid.title << vid.id << vid.duration << vid.viewCount;
        vidlist.append(vid);
    }

    emit newSearchDone(Playlist("search", vidlist));
}
